package com.fanrui.code.chess.mahjong;

import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import com.fanrui.code.chess.ChessGamerManager;
import com.fanrui.code.chess.ChessTableManager;
import com.fanrui.code.chess.IChessGamer;
import com.fanrui.code.chess.IPrivateChessTable;
import com.fanrui.code.entity.TableLog;
import com.fanrui.code.player.Player;
import com.fanrui.code.util.logger.Stdout;
import com.fanrui.proto.cmd.DissRoomAgreer;
import com.fanrui.proto.cmd.MahjongBaseRoomInfo.Builder;
import com.fanrui.proto.cmd.MahjongStep;
import com.fanrui.proto.cmd.NotifyDissolveMahjongRoom;
import com.fanrui.proto.cmd.NotifyIsDissolveMahjongRoom;
import com.fanrui.proto.cmd.ResDissolveMahjongRoom;
import com.fanrui.proto.cmd.ResJoinMahjongRoom;
import com.fanrui.proto.cmd.RoomDissolution;

public class PrivateMahjongTable extends AbstractMahjongTable<PrivateMahjongType> implements IPrivateChessTable {
	
	/**
	 * 房间解散信息
	 */
	private RoomDissolution.Builder roomDissolutionInfo;
	
	public PrivateMahjongTable(int ID, MahjongRules gameRules, long roomer) {
		super(ID, gameRules, new PrivateMahjongType());
		bankID = roomer;
	}
	
	@Override
	public com.fanrui.proto.cmd.ResJoinMahjongRoom.Result checkEnterCondition(Player player, boolean isReconnect) {
		ResJoinMahjongRoom.Result result = super.checkEnterCondition(player, isReconnect);
		if(result != ResJoinMahjongRoom.Result.Success) {
			return result;
		}
		IChessGamer<?> gamer = ChessGamerManager.getInstance().findGamer(player.getId());
		if ((gamer != null && gamer.getTableID() != getID()) || (gamer != null && !(gamer instanceof MahjongGamer))) {
			return com.fanrui.proto.cmd.ResJoinMahjongRoom.Result.Gaming;
		}
		return com.fanrui.proto.cmd.ResJoinMahjongRoom.Result.Success;
	}

	@Override
	public MahjongGamer findOrCreateGamer(Player player) {
		return ChessGamerManager.getInstance().create(player.getId(), getID(), MahjongGamer.class, player.getIp(), player.getX(), player.getY());
	}

	@Override
	public ResDissolveMahjongRoom.Result playerReqDissolveTable(IChessGamer<?> gamer, boolean agree) {
		if (roomDissolutionInfo == null) {// 第一次请求解散
			roomDissolutionInfo = RoomDissolution.newBuilder();
			roomDissolutionInfo.setSurplusTime(System.currentTimeMillis());
			agree = true;
			NotifyDissolveMahjongRoom.Builder notify = NotifyDissolveMahjongRoom.newBuilder();
			notify.setNickname(gamer.getPlayerInfo().getNickName());
			ChessTableManager.getInstance().findByID(getID()).broadcast(notify.build());
			defaultDissolve();
		}
		if (!checkInDissolutionInfo(gamer.getPlayerID())) {
			roomDissolutionInfo.addAgreer(DissRoomAgreer.newBuilder().setUserID(gamer.getPlayerID()).setType(agree ? 1 : 2).build());
			result();
			return ResDissolveMahjongRoom.Result.Success;
		} else {
			return ResDissolveMahjongRoom.Result.Failed;
		}
	}
	
	private boolean isCancel;
	
	public void defaultDissolve() {
		isCancel = false;
		Timer timer = new Timer();
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				if(isCancel) {
					timer.cancel();
					isCancel = false;
					return;
				}
				dissolvution(true);
			}
		}, 18000);
	}
	
	public boolean checkInDissolutionInfo(long playerId) {
		if (roomDissolutionInfo != null && roomDissolutionInfo.getAgreerCount() > 0) {
			for (DissRoomAgreer dra : roomDissolutionInfo.getAgreerList()) {
				if (dra.getUserID() == playerId) {
					return true;
				}
			}
		}
		return false;
	}
	
	public void result() {
		synchronized (this) {
			int result = getDissolveTable(gamers.size(), getRoundNum(), getStep());
			if (result == 1) {
				dissolvution(true);
			}
			if (result == -1) {
				dissolvution(false);
			}
		}
	}
	
	public DissRoomAgreer getDissolutionInfo(long playerId) {
		if (roomDissolutionInfo != null && roomDissolutionInfo.getAgreerCount() > 0) {
			for (DissRoomAgreer dra : roomDissolutionInfo.getAgreerList()) {
				if (dra.getUserID() == playerId) {
					return dra;
				}
			}
		}
		return null;
	}
	
	/**
	 * 解散房间结果
	 * 
	 * @return int 0 还不能判定是否能解散 1 可以解散 -1 不能解散
	 */
	public int getDissolveTable(int gamersSize, int round, MahjongStep mjStep) {
		if (roomDissolutionInfo != null || gamersSize > 0) {
			// 客户规定如果在没有开始的情况下房主可以直接解散房间
			if (MahjongStep.Wait.equals(mjStep) && round == 0 && checkInDissolutionInfo(bankID) && getDissolutionInfo(bankID).getType() == 1) {
				return 1;
			}

			int agree = 0;
			int unAgree = 0;
			for (DissRoomAgreer dra : roomDissolutionInfo.getAgreerList()) {
				if (dra.getType() == 1) {
					agree++;
				}
				if (dra.getType() == 2) {
					unAgree++;
				}
			}
			if (agree >= (gamersSize / 2) + 1 || gamersSize == 1) {
				return 1;
			}
			if (unAgree >= (gamersSize / 2 + gamersSize % 2)) {
				return -1;
			}
		}
		return 0;
	}

	@Override
	public void dissolvution(boolean success) {
		if (success) {// 解散房间
			isCancel = true;
			dissolveState = true;
			step = MahjongStep.Wait;// 因为在退出房间时 如果还在游戏中是不能退出的，所有这里将游戏结束
			NotifyIsDissolveMahjongRoom.Builder notifyDissolve = NotifyIsDissolveMahjongRoom.newBuilder();
			notifyDissolve.setResult(NotifyIsDissolveMahjongRoom.Result.Success);
			broadcast(notifyDissolve.build());
			nofityTotalResult();
			ChessTableManager.getInstance().destoryRoom(getID());
			ChessTableManager.getInstance().removePrivateTableByNo(getID());
			Stdout.GET().info("解散成功");
		} else {
			isCancel = true;
			dissolveState = false;
			roomDissolutionInfo = null;
			NotifyIsDissolveMahjongRoom.Builder notifyDissolve = NotifyIsDissolveMahjongRoom.newBuilder();
			notifyDissolve.setResult(NotifyIsDissolveMahjongRoom.Result.Failed);
			broadcast(notifyDissolve.build());
			Stdout.GET().info("解散失败");
		}
	}

	@Override
	public Collection<Long> needLeavePlayers() {
		return Collections.emptyList();
	}

	@Override
	public void otherBuilder(Builder builder) {
		
	}
	
	@Override
	protected TableLog createTableLog(long playerId, String playerNickName, String logToken, int income,
			String incomeInfo) {
		TableLog log = new TableLog();
		log.setGameType(this.getGameRules() instanceof GanZhouMahjongRules ? 0 : 1);
		log.setTableId(getID());
		log.setPlayerName(playerNickName);
		log.setLogToken(logToken);
		log.setPlayerId(playerId);
		log.setIncome(income);
		log.setIncomeInfo(incomeInfo);
		log.setInning(roundNum);
		log.setLogTime(new Date());
		log.setClubId(0);
		return log;
	}
	
}
